#include "VSend.h"
#include "ui_VSend.h"
#include "CHelper.h"
#include "CConversion.h"
#include "CUIHelper.h"
#include "CMainWindow.h"
#include "CSettings.h"
#include "ui_VQuickSend.h"
#include "ui_VReceiveTrig.h"
#include"QMessageBox"
#define SOH                     (0x01)  /* start of 128-byte data packet */
#define STX                     (0x02)  /* start of 1024-byte data packet */
#define EOT                     (0x04)  /* end of transmission */
#define ACK                     (0x06)  /* acknowledge */
#define NAK                     (0x15)  /* negative acknowledge */
#define CA                      (0x18)  /* two of these in succession aborts transfer */
#define CRC16                   (0x43)  /* 'C' == 0x43, request 16-bit CRC */

#define ABORT1                  (0x41)  /* 'A' == 0x41, abort by user */
#define ABORT2                  (0x61)  /* 'a' == 0x61, abort by user */




VSend::VSend(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VSend)
{
    ui->setupUi(this);

    //隐藏IP port输入
    ui->widget_address->hide();

    //发送键长按支持 @MAJR 触发时间随设置动态调整
    int nSpan = CSettings::getInstance()->settings()->value("Setting/Span").toInt();
    ui->pushButton_send->setAutoRepeat(true);
    ui->pushButton_send->setAutoRepeatInterval(nSpan);
    ui->pushButton_send->setAutoRepeatDelay(200);

    //初始化自动发送
    ui->spinBox_auto_span->hide();
    m_pTimerAutoSend = new QTimer(this);
    connect(m_pTimerAutoSend,&QTimer::timeout,[=]{
        on_pushButton_send_clicked();
    });

    //初始化快捷发送和 触发器
    for(int i = 0; i < 5; i++) {
        on_pushButton_quick_add_clicked();
        on_pushButton_trig_add_clicked();
    }

    connect(ui->comboBox_connections, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
        [=](int nIndex){
        EnmType enmItemData = (EnmType)ui->comboBox_connections->itemData(nIndex).toInt();

        switch(enmItemData){
        case EnmType::ENM_ALL_CONNECT:
            ui->widget_address->hide();
            break;
        case EnmType::ENM_CUSTOM_CONNECT:
            ui->widget_address->show();
            break;
        case EnmType::ENM_IP_PORT:
            ui->widget_address->hide();
            break;
        default:
            break;
        }
    });

    ui->progressBar_send->setValue(0);

}

VSend::~VSend()
{
    delete ui;
}

void VSend::setConnectionProxy(CConnectManager *pConnectManager)
{
    m_pConnectManager = pConnectManager;
    connect(m_pConnectManager,&AbsConnection::sigStateChanged,[=](AbsConnection::EnmState enmState){
        this->stateChanged(enmState);
    });
    connect(m_pConnectManager,&AbsConnection::sigConnectChanged,[=](QString strIp,quint16 nPort,bool bState){
        this->connectStateChanged(strIp,nPort,bState);
    });
    connect(m_pConnectManager,&AbsConnection::sigDataArrive,[=](QString strIp,quint16 nPort,QByteArray byteArr){
        this->dataArrive(strIp,nPort,byteArr);
    });
    connect(m_pConnectManager,&CConnectManager::sigProtocolChanged,[=](AbsConnection::EnmProtocolType enmType){
        this->protocolChanged(enmType);
    });
}

void VSend::protocolChanged(AbsConnection::EnmProtocolType enmType)
{
    //清除之前的连接 更改了协议已经失效
    ui->comboBox_connections->clear();

    switch(enmType){
    case AbsConnection::ENM_TCP_CLIENT:
    case AbsConnection::ENM_SERIAL:
    {
        ui->comboBox_connections->hide();
        ui->widget_address->hide();
    }break;
    case AbsConnection::ENM_TCP_SERVER:
    {
        ui->comboBox_connections->show();
        ui->widget_address->hide();

        ui->comboBox_connections->addItem(tr("所有连接"),EnmType::ENM_ALL_CONNECT);
    }break;
    case AbsConnection::ENM_UDP:
    {
        ui->comboBox_connections->show();
        ui->widget_address->show();

        ui->comboBox_connections->addItem(tr("手动设置"),EnmType::ENM_CUSTOM_CONNECT);
        ui->comboBox_ip->clear();
        ui->comboBox_ip->addItems(CHelper::localIPv4List());
        ui->comboBox_ip->setCurrentIndex(ui->comboBox_ip->count() - 1);
    }break;
    default:
        break;
    }
}

void VSend::connectStateChanged(QString strIp, quint16 nPort, bool bState)
{
    QString strKey = strIp + ":" +QString::number(nPort);

    int nIndex = ui->comboBox_connections->findText(strKey);
    if(bState) {
        if(-1 == nIndex) //连接成功 不存在就加上
            ui->comboBox_connections->addItem(strKey,EnmType::ENM_IP_PORT);
    } else {
        if(-1 != nIndex) //断开连接 存在就删掉
            ui->comboBox_connections->removeItem(nIndex);
    }
}

void VSend::dataArrive(QString strIp, quint16 nPort, QByteArray byteArr)
{


    QByteArray temp=byteArr;
    foreach(VReceiveTrig *pReceiveTrig,m_vecReceiveTrig) {
        pReceiveTrig->slotDataArrive(strIp,nPort,byteArr);
    }
    if(ymodem_enable) // ymodem 启动中
    {
        RxData.clear();
        RxData.append(temp);
        if(RxData.size()<0) return;
        qDebug("receive a data 0x%02X, byte arr 0x%02x , STEP %d",RxData.at(0),byteArr.at(0),Step);

        switch(Step){
        case 0:                                  //等待收方的请求
        {
            if(RxData.at(0) != 'C')
                break;

            //tm_timeout->stop();
            qDebug()<<"get ack 0";

            AckFlag='C';
            sgn_recvACK();        //传输开始

            Step=1;
            break;
        }
        case 1:                                //等待响应
        {
            if(RxData.size()==1)
            {
                if(RxData.at(0)=='C')       //只有C
                {
                    qDebug()<<"only C 1";

                    AckFlag='C';
                    sgn_recvACK();
                    Step=3;
                }
                else if(RxData.at(0)==ACK)      //只有ACK
                {
                    qDebug()<<"only ACK 1";
                }
            }
            else
            {
                if(RxData.at(0)==ACK&&RxData.at(1)=='C')        //同时ACK C
                {
                    qDebug()<<"get ack and C";

                    AckFlag='C';
                    sgn_recvACK();
                    Step=3;
                }
            }
            break;
        }
        case 2:                                //第二次等待对方的请求
        {
            if(RxData.at(0) != 'C')
                break;

            AckFlag='C';
            sgn_recvACK();
            Step=3;

            break;
        }
        case 3:                                //发送文件数据包
        {
            if(RxData.at(0) != ACK)
                break;

            ui->progressBar_send->setValue(PackCnt*100/PackNumber);                    //正式传输文件进度

            TxData.remove(0, SendLen);          //回复正确删除已发的长度

            if(PackCnt >= PackNumber){         //发送完成
                Step=4;
            }
            qDebug()<<"data ack and remove len"<<SendLen;
            sgn_recvACK();
            break;
        }
        case 4:                                //等待ACK C响应
        {
            qDebug("receive a data 0x%02X",RxData.at(0));

            if(RxData.size()==1)
            {
                if(RxData.at(0)=='C')       //只有C
                {
                    qDebug()<<"only C";

                    sgn_recvACK();
                    Step=6;
                    //slt_send_Handle(3);        //直接发送空包
                }
                else if(RxData.at(0)==ACK)      //只有ACK
                {
                    qDebug()<<"only ACK";
                }
                else if(RxData.at(0)==NAK)
                {
                    sgn_recvACK();
                }
            }
            else
            {
                if(RxData.at(0)==ACK&&RxData.at(1)=='C')        //同时ACK C
                {
                    qDebug()<<"get ack and C";

                    sgn_recvACK();
                    Step=6;
                }
            }
            break;
        }
        case 5:                                //第三次等待C字符
        {
            if(RxData.at(0) != 'C')
                break;

            qDebug()<<"get C";
            Step=6;
            break;
        }
        case 6:                                //
        {
            if(RxData.at(0) != ACK)
                break;

            qDebug()<<"get the null pkg ack,ftp end";
            sgn_recvACK();

            break;
        }

        }



    }


}

void VSend::processSendText(QString &strText, bool &bHex)
{
    //字符串转二进制
    QByteArray byteArr;
    if(bHex){
        bool bIsOk;
        byteArr = CConversion::hexStr2ByteArray(strText,&bIsOk);
        if (false == bIsOk) {
            CUIHelper::showHintInfo(tr("十六进制字符有误"),CMainWindow::getInstance());
            CUIHelper::widgetShake(ui->textEdit_send,5); //抖动提示
            qWarning()<<"十六进制文本输入格式有误:"<<strText;
        }
    }else{
        byteArr = CSettings::getInstance()->str2ByteArray(strText);  //根据设置的字符编码 进行String转换byteArr
    }

    //确定发送对象 并发送
    int nIndex = ui->comboBox_connections->currentIndex(); //获取当前索引

    EnmType enmItemData = (EnmType)ui->comboBox_connections->itemData(nIndex).toInt();

    switch(enmItemData){
    case EnmType::ENM_ALL_CONNECT:
    {
        m_pConnectManager->sendAll(byteArr);
    }
        break;
    case EnmType::ENM_CUSTOM_CONNECT:
    {
        QString strIp = ui->comboBox_ip->currentText();
        int nPort = ui->lineEdit_port->text().toInt();
        m_pConnectManager->send(strIp,nPort,byteArr);
    }
        break;
        //如 127.0.0.1:8009
    case EnmType::ENM_IP_PORT:
    {
        QString strKey = ui->comboBox_connections->currentText();
        QStringList strListTemp = strKey.split(":");
        if(2 == strListTemp.size()){
            m_pConnectManager->send(strListTemp.first(),strListTemp.last().toInt(),byteArr);
        }
    }
        break;
    default:
        qWarning()<<"类型错误!!!";
        break;
    }
}


void VSend:: send_data(QByteArray byteArr )
{
    //确定发送对象 并发送
    int nIndex = ui->comboBox_connections->currentIndex(); //获取当前索引

    EnmType enmItemData = (EnmType)ui->comboBox_connections->itemData(nIndex).toInt();

    switch(enmItemData){
    case EnmType::ENM_ALL_CONNECT:
    {
        m_pConnectManager->sendAll(byteArr);
    }
        break;
    case EnmType::ENM_CUSTOM_CONNECT:
    {
        QString strIp = ui->comboBox_ip->currentText();
        int nPort = ui->lineEdit_port->text().toInt();
        m_pConnectManager->send(strIp,nPort,byteArr);
    }
        break;
        //如 127.0.0.1:8009
    case EnmType::ENM_IP_PORT:
    {
        QString strKey = ui->comboBox_connections->currentText();
        QStringList strListTemp = strKey.split(":");
        if(2 == strListTemp.size()){
            m_pConnectManager->send(strListTemp.first(),strListTemp.last().toInt(),byteArr);
        }
    }
        break;
    default:
        qWarning()<<"类型错误!!!";
        break;
    }


}
void VSend::on_pushButton_send_clicked()
{
    QString strText = ui->textEdit_send->toPlainText();

    bool bIsHex = ui->checkBox_hex->isChecked();
    this->processSendText(strText,bIsHex);
}

void VSend::on_checkBox_auto_send_clicked(bool checked)
{
    ui->pushButton_send->setEnabled(!checked);
    if(checked){
        ui->spinBox_auto_span->show();
        m_pTimerAutoSend->start(ui->spinBox_auto_span->value());
    }else{
        ui->spinBox_auto_span->hide();
        m_pTimerAutoSend->stop();
    }
}

void VSend::on_spinBox_auto_span_valueChanged(int arg1)
{
    if(ui->checkBox_auto_send->isChecked()) {
        m_pTimerAutoSend->start(arg1);
    }
}

void VSend::on_tabWidget_currentChanged(int index)
{
    if(index < ui->stackedWidget->count()){
        ui->stackedWidget->setCurrentIndex(index);
    }
}

void VSend::selectQuickSend(VQuickSend *pQuickSend)
{
   //设置选中的快捷信息
    pQuickSend->setChecked(true);
    if(nullptr != m_pSelectedQuickSend && (m_pSelectedQuickSend != pQuickSend)) {
        m_pSelectedQuickSend->setChecked(false);
    }

    m_pSelectedQuickSend = pQuickSend;
}

void VSend::selectReceiveTrig(VReceiveTrig *pReceiveTrig)
{
    pReceiveTrig->setChecked(true);
    if(nullptr != m_pSelectedReceiveTrig && (m_pSelectedReceiveTrig != pReceiveTrig)) {
        m_pSelectedReceiveTrig->setChecked(false);
    }

    m_pSelectedReceiveTrig = pReceiveTrig;
}

void VSend::on_pushButton_quick_add_clicked()
{
    //添加一个快捷发送
    VQuickSend *pQuickSend = new VQuickSend(this);

    //选中时
    connect(pQuickSend,&VQuickSend::sigSelected,[=](VQuickSend *p){ //@TODO 可删掉此参数
        selectQuickSend(p);
    });
    //点击发送按钮
    connect(pQuickSend,&VQuickSend::sigSendClicked,[=](StQuickSend stData){
        processSendText(stData.strText,stData.bHex);
    });

    m_vecQuickSend.append(pQuickSend);
    QVBoxLayout *pLayout = qobject_cast<QVBoxLayout *>(ui->scrollAreaWidgetContents->layout());
    if(nullptr != pLayout) {
        pLayout->insertWidget(pLayout->count()-1,pQuickSend);
    }

}

void VSend::on_pushButton_quick_del_clicked()
{
    //删除一个快捷发送
    if(nullptr != m_pSelectedQuickSend){
        int nRemoveIndex = m_vecQuickSend.indexOf(m_pSelectedQuickSend);
        m_vecQuickSend.removeAt(nRemoveIndex);
        m_pSelectedQuickSend->deleteLater();
        m_pSelectedQuickSend = nullptr;

        //删除选中的  再默认选中一个
        if(!m_vecQuickSend.isEmpty()){
            if(nRemoveIndex < m_vecQuickSend.count()){
                selectQuickSend(m_vecQuickSend[nRemoveIndex]);
            }else{
                selectQuickSend(m_vecQuickSend.first());
            }
        }
    }
}

void VSend::on_checkBox_quick_hex_clicked(bool checked)
{
    foreach (VQuickSend *pQuickSend,m_vecQuickSend) {
        pQuickSend->ui->checkBox->setChecked(checked); //需包含 ui_xxx头文件才可用
    }
}

void VSend::on_spinBox_quick_span_valueChanged(int arg1)
{
    foreach (VQuickSend *pQuickSend,m_vecQuickSend) {
        pQuickSend->ui->spinBox->setValue(arg1);
    }
}

void VSend::on_pushButton_loop_start_clicked(bool checked)
{
    //循环快捷发送

    //判空
    if(m_vecQuickSend.isEmpty()){
        CUIHelper::showHintInfo(tr("没有数据可循环发送!"),CMainWindow::getInstance());
        return ;
    }

    //修改循环按钮文本
    ui->pushButton_loop_start->setText(checked ? "停止循环" : "开始循环");

    //定时器 懒创建
    if(nullptr == m_pTimerLoopQuickSend) {
        m_pTimerLoopQuickSend = new QTimer(this);
        connect(m_pTimerLoopQuickSend,&QTimer::timeout,[=]{

            //发送选中的信息
            StQuickSend stInfo = m_vecQuickSend[m_nCurrentSendIndex]->info();
            processSendText(stInfo.strText,stInfo.bHex);

            //调整时间间隔
            if(m_pTimerLoopQuickSend->interval() != stInfo.nSpan) {
                m_pTimerLoopQuickSend->start(stInfo.nSpan);
            }

            //定位到下个非空快捷发送 @BUG info() 返回空
            do{
                ++m_nCurrentSendIndex;
                m_nCurrentSendIndex = m_nCurrentSendIndex % m_vecQuickSend.count();
            }while(m_vecQuickSend[m_nCurrentSendIndex]->info().strText.isEmpty());


            //调整选中状态
            selectQuickSend(m_vecQuickSend[m_nCurrentSendIndex]);
        });
    }

    //启动或关闭定时器
    if (checked) {
        // !!! 防止删除信息 导致索引越界
        if(m_nCurrentSendIndex < 0 || (m_nCurrentSendIndex >= m_vecQuickSend.count())){
            m_nCurrentSendIndex = 0;
        }

        int nSpan = m_vecQuickSend[m_nCurrentSendIndex]->info().nSpan;
        m_pTimerLoopQuickSend->start(nSpan);
    } else {
        m_pTimerLoopQuickSend->stop();
    }

    //禁用或启用  添加、删除
    ui->pushButton_quick_add->setEnabled(!checked);
    ui->pushButton_quick_del->setEnabled(!checked);
}

/*****************************触发器部分************************************/

void VSend::on_pushButton_trig_add_clicked()
{
    VReceiveTrig *pReceiveTrig = new VReceiveTrig(this);

    //选中时
    connect(pReceiveTrig,&VReceiveTrig::sigSelected,[=]{
        selectReceiveTrig(pReceiveTrig);
    });
    //触发时
    connect(pReceiveTrig,&VReceiveTrig::sigReceiveTrig,[=](StReceiveTrig stData){
        qDebug()<<"VSend::on_pushButton_trig_add_clicked()"<<"触发";
        if(ui->pushButton_trig_start->isChecked()) { //触发器启用时
            qDebug()<<"VSend::on_pushButton_trig_add_clicked()"<<"触发"<<stData.strSText<<stData.bHex;
            processSendText(stData.strSText,stData.bHex); //发送出去
        }
    });
    //绑定消息接收
//    connect(m_pConnectManager,&CConnectManager::sigDataArrive,pReceiveTrig,&VReceiveTrig::slotDataArrive);

    QVBoxLayout *pLayout = qobject_cast<QVBoxLayout *>(ui->scrollAreaWidgetContents_trig->layout());
    if(nullptr != pLayout) {
        pLayout->insertWidget(pLayout->count()-1,pReceiveTrig);
    }

    m_vecReceiveTrig.append(pReceiveTrig);
}

void VSend::on_pushButton_trig_del_clicked()
{
    if(nullptr != m_pSelectedReceiveTrig){
        int nRemoveIndex = m_vecReceiveTrig.indexOf(m_pSelectedReceiveTrig);
        m_vecReceiveTrig.removeAt(nRemoveIndex);
        m_pSelectedReceiveTrig->deleteLater();
        m_pSelectedReceiveTrig = nullptr;
        //删除选中的  再默认选中一个
        if(!m_vecReceiveTrig.isEmpty()){
            if(nRemoveIndex < m_vecReceiveTrig.count()){
                selectReceiveTrig(m_vecReceiveTrig[nRemoveIndex]);
            }else{
                selectReceiveTrig(m_vecReceiveTrig.first());
            }
        }
    }
}

void VSend::on_checkBox_trig_hex_clicked(bool checked)
{
    foreach(VReceiveTrig *pReceiveTrig,m_vecReceiveTrig) {
        pReceiveTrig->ui->checkBox->setChecked(checked); //需包含 ui_xxx头文件才可用
    }
}

void VSend::on_pushButton_trig_start_clicked(bool checked)
{
    //修改循环按钮文本
    ui->pushButton_trig_start->setText(checked ? tr("禁用触发器") : tr("启用触发器"));
}

void VSend::on_toolButton_clear_clicked()
{
    ui->textEdit_send->clear();

}

void VSend::on_pushButton_chose_clicked()
{
    //打开传输的文件


    QSettings *configIniWrite = new QSettings("file_save_addr.ini", QSettings::IniFormat);// 文件存储地址
    FilePath = configIniWrite->value("/file/addr").toString();
    FilePath = QFileDialog::getOpenFileName(this, QString("选择文件"), QString(FilePath),QString("file(*.*)"));

    configIniWrite->setValue("/file/addr", FilePath);



    if (FilePath.isEmpty())
        return;

    QFile *ftpfile=new QFile(FilePath);
    if (!ftpfile->open(QFile::ReadOnly)){     //不能带QFile::Text，因为文本格式是不会去读0x0D的，导致读取到的数据会将0x0D去除掉
        qDebug()<<"Open file err";
    }
    TxData=ftpfile->readAll();
    ftpfile->close();

    PackSize=1024;
    PackNumber = TxData.size() / PackSize;//计算包数
    if(TxData.size() % PackSize)              //多出的按一包算
     PackNumber += 1;
    qDebug()<<"File size="<<TxData.size()<<" PackNumber="<<PackNumber;

    ui->file_path->setText(FilePath);
   // led_filePath->setText(FilePath);
}
int VSend::ackwait(int to)
{
    QEventLoop loop;
    QTimer timeout_t;
    timeout_t.setSingleShot(true);
    connect(&timeout_t,SIGNAL(timeout()),&loop,SLOT(quit()));
    connect(this,SIGNAL(sgn_recvACK()),&loop,SLOT(quit()));
    timeout_t.start(to);
    loop.exec();
  // qDebug()<<"wait end";
//    qDebug()<<timeout_t.remainingTime();

    if(timeout_t.isActive())
    {
        //RxData.clear();

        qDebug()<<"ack ok";
        return 1;
    }
    else
    {
        qDebug()<<"wait ack timeout";
        return -1;
    }
}
//多项是为0x1021的CRC算法
qint16 VSend::GetCrc(QByteArray Data)
{
   quint16 mCrc = 0;
   quint16 sLen = Data.size();
   for(quint32 j = 0; j < sLen; j++){
       mCrc = mCrc^(quint16)(Data.at(j)) << 8;
       for (quint32 i=8; i!=0; i--){
           if (mCrc & 0x8000)
               mCrc = mCrc << 1 ^ 0x1021;
           else
               mCrc = mCrc << 1;
       }
   }
   return mCrc;
}
void VSend::on_pushButton_send_file_clicked()
{
    quint16 ValidLen = 0;
    QByteArray Pack, Data;
    quint8 cnt = 0;                               //xModem 包号从1开始
    quint16 Crc;
    int ackval=0;

    ymodem_enable = 1;
    ui->pushButton_send_file->setText("发送中");
    if(FilePath.isEmpty())
    {
        QMessageBox *msgBox=new QMessageBox(this);                     //串口未打开，创建一个消息提醒框
        msgBox->setWindowTitle(tr("Notice"));
        msgBox->setText(tr("Please Select a file!"));
        //msgBox->setInformativeText(tr("Please open a serialport!"));
        //msgBox->setDetailedText(tr("Differences here..."));
        msgBox->setStandardButtons(QMessageBox::Ok);
        msgBox->setDefaultButton(QMessageBox::Ok);
        int ret = msgBox->exec();
        if(ret == QMessageBox::Ok)
            return;     //串口未打开，禁止发送
        else
            return;
    }

    Step=0;
    PackCnt=0;
    PackIndex=0;




/***********************************************************************/
    RxData.clear();


    TxData.clear();
    QFile *ftpfile=new QFile(FilePath);
    if (!ftpfile->open(QFile::ReadOnly)){     //不能带QFile::Text，因为文本格式是不会去读0x0D的，导致读取到的数据会将0x0D去除掉
        qDebug()<<"Open file err";
    }
    TxData=ftpfile->readAll();
    ftpfile->close();




    qDebug()<<"start";
    ackval=ackwait(20000);
    if(ackval<=0)   {RxData.clear();return;}
    else{
        if(RxData.at(0)!='C')   {RxData.clear();
            ui->lineEdit_state->setText("get ack filed");
            return;}
    }
/***********************************************************************/
    qDebug()<<"send file info";
    Pack.resize(3);
    PackIndex=0;                             //设置包序号
    Pack[0] = SOH;
    Pack[1] = PackIndex;                      //包号
    Pack[2] = ~PackIndex;                     //包号取反

//    Pack+=FilePath.section('/',-1).toLocal8Bit();      //添加文件名
//    Pack+='\0';
    Pack += "test.rbl";
    Pack += '\0';
    Pack += QString("%1").arg(TxData.size());
    Pack += '\0';
    Pack.resize(128+3);

    //Pack+=QString::number(TxData.size());


    //int len=Pack.length()-3;   //出去头部和序列号的长度
//    if(len<128)
//    {
//       QByteArray zero(128 - len, 0x00); //不足部分填充0x00
//       qDebug()<<"creat zero section";
//       Pack+=zero;
//    }
    Crc = GetCrc(Pack.mid(3,128));                 //CRC
    Pack += (quint8)(Crc >> 8);         //先发高位
    Pack += (quint8)(Crc & 0xff);       //后发低位

    qDebug()<<"write data to port";
    Pack.resize(128+5);
    send_data(Pack);// Port->write(Pack, 128 + 5);    //发送数据

    qDebug()<<"write end";
    qDebug()<<"send file info end";
    Pack.clear();                       //清buf
    Data.clear();                       //清buf

    RxData.clear();

    //return;

    ackval=ackwait(20000);            //超时2s
    if(ackval<=0)   {ui->lineEdit_state->setText("wait head ack filed 1"); RxData.clear();ymodem_enable = 0;return;}
    else{
//        if(RxData.size()==1)
//        {
//            if(RxData.at(0)!='C')   {RxData.clear();   return;}
//        }
//        if(RxData.size()>1)
//        {
//            if(RxData.at(0)!=ACK||RxData.at(1)!='C')   {RxData.clear();return;}
//        }
    }
/***********************************************************************/
    for(int i=0;i<PackNumber;i++)
    {
        PackIndex++;
        qDebug()<<"PackIndex="<<PackIndex;
        Pack.resize(3);

        Pack[0] = STX;                     //目前只用1024byte类型
        Pack[1] = PackIndex;                      //包号
        Pack[2] = ~PackIndex;                     //包号取反
        ValidLen = TxData.size();           //有效数据长度
        if(ValidLen >= PackSize){           //大于包长
            Data = TxData.left(PackSize);   //从TxData的左侧取出PackSize长
            SendLen = PackSize;             //已发长度
        }else{
            QByteArray zero(PackSize - ValidLen, 0x1A); //不足部分填充0x1A
            Data = TxData.left(ValidLen);   //不足一包
            Data += zero;                   //填充其它数据
            SendLen = ValidLen;             //已发长度
        }
        Data.resize(1024);
        Crc = GetCrc(Data);                 //CRC
        Pack += Data;                       //填入数据
        Pack += (quint8)(Crc >> 8);         //先发高位
        Pack += (quint8)(Crc & 0xff);       //后发低位
        Pack.resize(1024+5);
        send_data(Pack); // Port->write(Pack, PackSize + 5);    //发送数据

        Pack.clear();                       //清buf
        Data.clear();                       //清buf



        PackCnt++;
        qDebug()<<"PackCnt="<<PackCnt;

        RxData.clear();
        ackval=ackwait(20000);            //超时1s
        if(ackval<=0)   {
            RxData.clear();
            ymodem_enable = 0;
            ui->lineEdit_state->setText("not recv data ack 2 ");

            return;
          }
        else{
//            if(RxData.at(0)!=ACK)   {RxData.clear();return;}
        }
    }
/***********************************************************************/
    while(1)
    {
        qDebug()<<"send EOT";
        Pack.clear();                      //清除buf
        Pack += EOT;                      //发送结束符
       send_data(Pack);// Port->write(Pack, 1);              //写
        Pack.clear();

        RxData.clear();
        ackval=ackwait(3000);            //超时1s
       if(ackval<=0)   {RxData.clear();return;}
        else{
           if(RxData.size()==1)
           {
                if(RxData.at(0)=='C')   {RxData.clear();break;}
                else if(RxData.at(0)!=NAK)  {RxData.clear();return;}
           }
           else if(RxData.size()>1)
           {
                if(RxData.at(0)==ACK&&RxData.at(1)=='C')    {RxData.clear();break;}
           }
        }
    }

/***********************************************************************/
    qDebug()<<"send null pkg to end";
    cnt = 0;
    Pack[0] = SOH;                      //目前只用128byte类型
    Pack[1] = cnt;                      //包号
    Pack[2] = ~cnt;                     //包号取反
    QByteArray zero(128, 0x00);         //填充0x00
    Crc = GetCrc(zero);                 //CRC
    Pack += zero;                       //填入数据
    Pack += (quint8)(Crc >> 8);         //先发高位
    Pack += (quint8)(Crc & 0xff);       //后发低位
    Pack.resize(128+5);
    send_data(Pack);// Port->write(Pack, 128 + 5);         //发送数据
    Pack.clear();                       //清buf
    Data.clear();                       //清buf

    RxData.clear();
    ackval=ackwait(1000);               //超时1s
    if(ackval<=0)   {RxData.clear();return;}
    else{
        if(RxData.at(0)!=ACK)   {RxData.clear();return;}
    }
     ui->pushButton_send_file->setText("Ymodem发送");
/***********************************************************************/
    //this->close();
}
